package com.zkh.myutils.io;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
import java.util.function.Function;
import com.zkh.myutils.io.log.Logger;

/**
 * IO相关工具类
 * @author zkh
 */
public class IOUtils {
	
	/**
	 * 静默关闭流
	 * @param closeables 可关闭对象数组
	 */
	public static void closeQuietly(AutoCloseable... closeables) {
		for(AutoCloseable closeable: closeables) {
			if(closeable!=null) {
				try {
					closeable.close();
				} catch (Exception e) {
					Logger.error(e);
				}
			}
		}
	}
	
	/**
	 * 静默关闭流
	 * @param closeable 可关闭对象数组
	 * @param fun 自定义异常函数
	 */
	public static void closeQuietly(AutoCloseable closeable, Function<Exception, RuntimeException> fun) {
		if(closeable!=null) {
			try {
				closeable.close();
			} catch (Exception e) {
				throw fun.apply(e);
			}
		}
	}
	
	/**
	 * 将输入流转换为字节数组
	 * @param inputStream 指定输入流
	 * @return 字节数组
	 * @throws IOException 读取流数据时可能发生异常
	 */
	public static byte[] toByteArray(InputStream inputStream) throws IOException{
		// 非空
		Objects.requireNonNull(inputStream);
		//开始读取
		try(ByteArrayOutputStream os = new ByteArrayOutputStream(inputStream.available())){
			//临时变量
			int len;
			byte[] bytes = new byte[1024];
			//循环读取数据
			while((len=inputStream.read(bytes))!=-1) {
				os.write(bytes, 0, len);
			}
			//返回字节数组
			return os.toByteArray();
		}
	}
	
	/**
	 * 
	 * 复制流数据。默认缓冲为1024
	 * @param source 原流
	 * @param dest 目标流
	 * @return 返回流大小
	 */
	public static long copyStream(InputStream source, OutputStream dest) throws IOException {
		return copyStream(source, dest, -1);
	}
	
	/**
	 * 复制流数据
	 * @param source 原流
	 * @param dest 目标流
	 * @param bufferSize 缓冲大小，大于-1时生效
	 */
	public static long copyStream(InputStream source, OutputStream dest, int bufferSize) throws IOException {		
		return copyStream(source, dest, bufferSize > 0 ? bufferSize : 1024, false);
	}
	
	/**
	 * 
	 * 使用BufferedInputStream复制流数据。默认缓冲为1024
	 * @param source 原流
	 * @param dest 目标流
	 * @return 返回流大小
	 */
	public static long copyStreamBuffer(InputStream source, OutputStream dest) throws IOException {
		return copyStreamBuffer(source, dest, -1);
	}
	
	/**
	 * 使用BufferedInputStream复制流数据
	 * @param source 原流
	 * @param dest 目标流
	 * @param bufferSize 缓冲大小，大于-1时生效
	 */
	public static long copyStreamBuffer(InputStream source, OutputStream dest, int bufferSize) throws IOException {
		return copyStream(source, dest, bufferSize > 0 ? bufferSize : 1024, true);
	}
	
	/**
	 * 复制流公共方法
	 * @param source 源流
	 * @param dest 目标流
	 * @param bufferSize 缓冲大小
	 * @param buffer 是否使用BufferedInputStream包装
	 */
	private static long copyStream(InputStream source, OutputStream dest, int bufferSize, boolean buffer) throws IOException {
		//检查空
		Objects.requireNonNull(source);
		//包装缓冲流（如果使用）
		InputStream is = buffer ? new BufferedInputStream(source) : source;
		try {
			//字节数组
			byte[] bytes = new byte[bufferSize];
			//临时长度
			int len;
			//总长度
			long size = 0;
			//读取源文件并写入压缩文件
			while ((len = is.read(bytes)) != -1) {
				//写数据
				dest.write(bytes, 0, len);
				dest.flush();
				//累加总长度
				size += len;
			}
			//返回大小
			return size;
		} finally {
			//关闭输入流
			if(buffer) {
				is.close();
			}
		}
	}
}
